package com.zyj.spring.annotationaop.util;

import com.zyj.spring.annotationaop.annatation.NeedSetValue;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Objects;

@Component
public class BeanUtil implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void setBeanFieldValue(Collection collection) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {

        Class<?> targetClazz = collection.iterator().next().getClass();

        Field[] targetFields = targetClazz.getDeclaredFields();

        // 循环 需要设值的实体类 的字段
        for (Field field : targetFields) {

            // 判断是否包含 NeedSetValue 注解
            NeedSetValue needSetValue = field.getAnnotation(NeedSetValue.class);
            if (Objects.isNull(needSetValue)) {
                continue;
            }

            field.setAccessible(true);

            // UserDao
            Object dataBean = this.applicationContext.getBean(needSetValue.beanName());
            // selectOne
            Method dataMethod = needSetValue.beanName().getMethod(needSetValue.method(), targetClazz.getDeclaredField(needSetValue.param()).getType());
            // Order.customerId
            Field dataField = targetClazz.getDeclaredField(needSetValue.param());
            dataField.setAccessible(true);

            Field targetField = null;
            boolean needInnerField = !StringUtils.isEmpty(needSetValue.targetField());

            // Order
            for (Object obj : collection) {

                // Order.customerId（value）
                Object paramValue = dataField.get(obj);

                if (Objects.isNull(paramValue)) {
                    continue;
                }

                // 执行UserDao.selectOne(customerId)，获取User
                Object value = dataMethod.invoke(dataBean, paramValue);

                if (needInnerField) {
                    if (Objects.nonNull(value)) {
                        if (Objects.isNull(targetField)) {
                            // User.name
                            targetField = value.getClass().getDeclaredField(needSetValue.targetField());
                            targetField.setAccessible(true);
                        }
                        value = targetField.get(value);
                    }
                }
                field.set(obj, value);
            }
        }
    }
}
